package com.formula.datastructure.question.stack;

import com.formula.datastructure.standard.stack.Stack;

public class Expression {

    private Stack<Character> optStack;
    private Stack<Integer> numStack;

    public int calculate(String input) {

        char[] str = input.toCharArray();

        optStack = new Stack<>();
        numStack = new Stack<>();

        for (int i = 0; i < str.length; i++) {
            Character c = str[i];
            System.out.println("The input : " + c);
            if (isNumber(c)) {
                //也可以用转换
                numStack.push(c - 48);
            } else {
                if (optStack.isEmpty()) {
                    optStack.push(c);
                } else {
                    switch (compareWithTop(c)) {
                        case '>': //优先级比栈顶元素大 ，则入栈,并接收下一个字符
                            optStack.push(c);
                            break;
                        case '=': //优先级和栈顶元素相同, 脱括号
                            optStack.pop();
                            break;
                        case '<': // 优先级比栈顶元素小，则操作数出栈，操作符出栈，运算之后入栈。即意思是优先级高的先运算
                            int b = numStack.pop();//顺序靠后的操作数
                            int a = numStack.pop();//顺序靠前的操作数
                            numStack.push(operate(a, b, optStack.pop()));
                            if (c == ')' && optStack.getTop() == '(') {
                                optStack.pop();
                            } else {

                            }
                            break;
                    }
                }
            }
            numStack.traverse();
            optStack.traverse();
        }

        return numStack.pop();
    }

    private char compareWithTop(Character c) {
        Character top = optStack.getTop();
        if (c == '#') {
            return '<';
        }
        if (c == '+' || c == '-') { //c为后进入的操作符，top为之前进入的操作符
            //如果同为+ - 则top的优先级大于c  同理 * /就更不用说了
            if (top == '+' || top == '-' || top == '*' || top == '/') {  //所以和栈顶元素相比 优先级要小
                return '<';
            }
            if (top == '(') {
                return '>';
            }
            if (top == ')') {
                return '<';
            }
            if (top == '#') {
                return '>'; //#是定义为预算结束的标志符 比所有的操作符优先级都小
            }
        }
        if (c == '*' || c == '/') {
            if (top == '+' || top == '-') {
                return '>';
            }

            if (top == '*' || top == '/') {
                return '<';
            }
            if (top == '(') {
                return '>';
            }
            if (top == ')') {
                return '<';
            }
        }


        if (c == '(') {
            return '>';
        }
        if (c == ')') {
            if (top != '(') {
                return '<';
            } else {
                return '=';
            }
        }
        return '<';
    }

    private int operate(int a, int b, char op) {
        switch (op) {
            case '+':
                return a + b;
            case '-':
                return a - b;
            case '*':
                return a * b;
            case '/':
                return a / b;
        }
        System.out.println("Invalid Input!!!");
        return 0;
    }


    private boolean isNumber(char c) {
        if (c == '+' || c == '-' || c == '*' || c == '/' || c == '(' || c == ')' || c == '#') {
            return false;
        } else {
            return true;
        }
    }

    public static void main(String[] args) {
        Expression expression = new Expression();
        String input = "(5-3)*(14+(23+3*3))/2-22#";
        System.out.println(expression.calculate(input));
    }
}
